/**
 * N*M的方阵，某些格子放了镜子，可以反射光线。改变一个镜子花费1
 * 光线从11的坐标输入，要求从NM的右侧射出，问最小花费
 * 首先注意不存在这种可能：某种合法的路径，要求某一格的镜子既是这样又是那样
 * 或者说光线不可能原路返回，即所有镜子的调整都是无后效的，只需考虑当前状态即可
 * 将状态记作xyo，即位于xy位置，光线射出o方向
 * 初始状态为(1, 0, YOU)，终态为(N, M, YOU)
 * 求一个最短路径即可。Dijkstra。
 */
#include <bits/stdc++.h>
using namespace std;

#include <bits/extc++.h>
using namespace __gnu_pbds;

using llt = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using _t = pair<int, array<int, 3>>;
__gnu_pbds::priority_queue<_t, function<bool(const _t&, const _t&)>> Q([](_t const & a, _t const & b){
    if(a.first != b.first) return a.first > b.first;
    for(int i=0;i<3;++i)if(a.second[i]!=b.second[i])return a.second[i]>b.second[i];
    return false;
});

int const ZHU = 1;
int const FUU = 2;
int const SHA = 0;
int const XIA = 1;
int const ZUO = 2;
int const YOU = 3;

int N, M, K;
vvi Board;
vector<vvi> D;

int hZhu(int o){
    if(o == YOU) return SHA;
    if(o == XIA) return ZUO;
    if(o == SHA) return YOU;
    if(o == ZUO) return XIA;
    assert(0);
}

int hFuu(int o){
    if(o == ZUO) return SHA;
    if(o == XIA) return YOU;
    if(o == SHA) return ZUO;
    if(o == YOU) return XIA;
    assert(0);
}

void g(int o, int x, int y, int w){
    switch(Board[x][y]){
        case 0:{
            auto no = o ^ 1;
            if(D[x][y][no] != -1) return;
            Q.push({w, {x, y, no}});
        }break;
        case ZHU:{
            int no = hZhu(o);
            if(D[x][y][no] == -1){
                Q.push({w, {x, y, no}});
            } 
            no = hFuu(o);
            if(D[x][y][no] == -1){
                Q.push({w + 1, {x, y, no}});
            }
        }break;
        case FUU:{
            int no = hFuu(o);
            if(D[x][y][no] == -1){
                Q.push({w, {x, y, no}});
            } 
            no = hZhu(o);
            if(D[x][y][no] == -1){
                Q.push({w + 1, {x, y, no}});
            }
        }break;
        default:assert(0);
    }
    return;
}

void f(int curx, int cury, int o, int w){
    switch(o){
        case SHA:{
            auto nx = curx - 1;
            if(nx >= 1){
                g(XIA, nx, cury, w);
            }
        }break;
        case XIA:{
            auto nx = curx + 1;
            if(nx <= N){
                g(SHA, nx, cury, w);
            }
        }break;
        case ZUO:{
            auto ny = cury - 1;
            if(ny >= 1){
                g(YOU, curx, ny, w);
            }
        }break;
        case YOU:{
            auto ny = cury + 1;
            if(ny <= M){
                g(ZUO, curx, ny, w);
            } 
        }break;
        default:assert(0);
    }
    return;
}

int proc(){
    D.assign(N + 1, vvi(M + 1, vi(4, -1)));
    Q.clear();
    f(1, 0, YOU, 0);
    while(1){
        while(not Q.empty()){
            auto h = Q.top();
            if(-1 != D[h.second[0]][h.second[1]][h.second[2]]) Q.pop();
            else break;
        }
        if(Q.empty()) break;

        auto h = Q.top(); Q.pop();
        if(h.second[0] == N and h.second[1] == M and h.second[2] == YOU){
            return h.first;
        }else{
            D[h.second[0]][h.second[1]][h.second[2]] = h.first;
        }
        f(h.second[0], h.second[1], h.second[2], h.first);
    }
    return -1;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(0);
    int nofkase = 1;
    // cin >> nofkase;
    while(nofkase--){
        cin >> N >> M >> K;
        Board.assign(N + 1, vi(M + 1, 0));
        for(int x,y,c,i=0;i<K;++i){
            cin >> x >> y >> c;
            // cout << 1 + c << endl;
            Board[x][y] = 1 + c;
        }
        cout << proc() << endl;
    }
    return 0;
}